#include "TokenSen.h"
#include "TokenSenCtrl.h"
#include "TokenIntExp.h"
#include "Value.h"
#include "TokenBoolExp.h"
#include "Token.h"
#include "VarTable.h"
#include "Error.h"
#include <string>
#include <cassert>
#include <iostream>
#include <sstream>
using namespace std;
void TokenSen::run(bool enabled /*= true*/)
{
	if (toParse.size() == 0)
		return;
	else if (toParse.substr(0, string("if").size()) == "if" && (toParse.size() <= string("if").size() || toParse[string("if").size()] == ' ')) // (toParse.find("if") != string::npos)
	{
		TokenSenIf tsi(toParse);
		tsi.run(enabled);
	}
	else if (toParse.substr(0, string("while").size()) == "while" && (toParse.size() <= string("while").size() || toParse[string("while").size()] == ' ')) // (toParse.find("while") != string::npos)
	{
		TokenSenWhile tsw(toParse);
		tsw.run(enabled);
	}
	else if (!enabled)
	{
		return;
	}
	else if (toParse.substr(0, string("break").size()) == "break" && (toParse.size() <= string("break").size() || toParse[string("break").size()] == ' ')) // (toParse.find("break") != string::npos)
	{
		if (enabled) throw ErrorBreak();
		//check empty!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	}
	else if (toParse.substr(0, string("print").size()) == "print" && (toParse.size() <= string("print").size() || toParse[string("print").size()] == ' ' || toParse[string("print").size()] == '\"' || toParse[string("print").size()] == '\'')) // (toParse.find("print") != string::npos)
	{
		TokenSenPrint tsp(toParse);
		if (enabled) tsp.run();
	}
	else if (toParse.substr(0, string("else").size()) == "else" && (toParse.size() <= string("else").size() || toParse[string("else").size()] == ' ' || toParse[string("else").size()] == ':')) // (toParse.find("print") != string::npos)
	{
		throw Error("Unexpected \"else\".");
	}
	else
	{
		//check if it is a raw expression, should be merged to TokenSenPrint and judge TokenSenAssign directly
		Context* ctx = Context::getInstance();
		int opp; // operator position
		int opc; // operator charater
		const int CmpSymNum = 9;
		string CmpSymbol[CmpSymNum] = {"==", "!=", "<>", "<=", "<", ">=", ">", "True", "False"}; // < is substring of <=, so <= must come first!
		for (opc = 0; opc < CmpSymNum; opc++)
		{
			opp = toParse.find(CmpSymbol[opc]);
			if (opp != string::npos)
				break;
		}
		if (opc < CmpSymNum)
		{
			TokenBoolExp tbe(toParse);
			if (enabled) (ctx -> stdOut()) << tbe.getResult() << endl;
		}
		else if (toParse.find("=") == string::npos)
		{
			TokenIntExp tie(toParse);
			ValueInt vi = tie.getResult();
			if (enabled) (ctx -> stdOut()) << vi.str() << endl;
		}
		else
		{
			TokenSenAssign tsa(toParse);
			if (enabled) tsa.run();
		}
	}
}
void TokenSenAssign::run(bool enabled /*= true*/)
{
	VarTable* t = VarTable::getInstance();
	int symPos = toParse.find("=");
	assert(symPos != string::npos);
	string varname = toParse.substr(0, symPos);
	TokenIntExp tie(toParse.substr(symPos+1, toParse.size()-1-symPos));
	ValueInt* pv = t -> get(varname);
	if (pv == NULL)
		t -> def(varname, tie.getResult());
	else
		pv -> assign(tie.getResult());
}
void TokenSenPrint::run(bool enabled /*= true*/)
{
	Context* ctx = Context::getInstance();
	int pPos = toParse.find("print");
	assert(pPos != string::npos);
	assert(pPos == 0);
	int start = string("print").size();
	string toPrint = toParse.substr(pPos+start, toParse.size()-(pPos+start)); // magic Numbers!!!
	if (toPrint == "")
		throw Error("Nothing to print.");
	istringstream sin(toPrint);
	char c;
	sin >> c;
	if (c == '"' || c == '\'')
	{
		char quote = c;
		int startOfStr = toPrint.find(quote);
		int endOfStr = toPrint.find(quote, startOfStr + 1);
		if (endOfStr == string::npos)
			throw Error("End quotation expected but not found.");
		(ctx -> stdOut()) << toPrint.substr(startOfStr + 1, endOfStr - startOfStr - 1) << endl;
		sin.str(toPrint.substr(endOfStr + 1, toPrint.size() - (endOfStr + 1)));
		string word;
		sin >> word;
		if (word != "")
				throw Error("Unexpected \"" + word + "\" after literal-string.");
	}
	else
	{
		if (toPrint[0] != ' ' && toPrint[0] != '\t')
			throw Error("Space expected after \"print\"."); // Never!!!
		TokenIntExp tie(toPrint);
		ValueInt vi = tie.getResult();
		(ctx -> stdOut()) << vi.str() << endl;
	}
}

